#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include <complex.h>
#include <fftw3.h>

#define pi 2*acos(0)
#define fmode FFTW_EXHAUSTIVE

typedef struct vector {
  fftw_complex *r, *v;
} vect;

typedef struct work {
  int n;
  double	y0;
  fftw_complex *Y, *Yk;
  double *YY, *YYk;
} work, *work_ptr;

typedef struct control {
  double H;  // energy
  double M;  // mean level
  double P;  // momentum
} ctrl, *ctrl_ptr;

typedef struct params {
  int n, skip, t_skip, fix_flag;
  double g, c, dtau, tol, alfa;
  char runname[80];
  char resname[80];
  ctrl current; 
  work_ptr w_ptr;
} params, *params_ptr;

//  --  ffts.c
extern void err_msg(char* str);
extern void init(int *argc, char **argv, params_ptr in, work_ptr wrk) ;
extern void hilbert(fftw_complex *in, fftw_complex *out);
extern void project(fftw_complex *in, fftw_complex *out);
extern void pproject(fftw_complex *in, fftw_complex *out);
extern void ffilter(fftw_complex *in);
extern void reconstruct_surface(work_ptr in);
extern void reconstruct_potential(work_ptr in); 
extern void update_dfunc(work_ptr in);
extern void fft(fftw_complex *in, fftw_complex *out);
extern void ifft(fftw_complex *in, fftw_complex *out);

extern void fft_even(double *in, double *out); 
extern void ifft_even(double *in, double *out); 

extern void der(fftw_complex *in, fftw_complex *out);
extern void rhs(work_ptr in, int m);
extern void rk4(params_ptr in);

extern void generate_derivatives(work_ptr in, int m);
extern void clean_spectrum(fftw_complex *in, fftw_complex *out);
extern void prepare_rhs(work_ptr wrk);
extern void iterate(work_ptr wrk);
extern void iterate_cg(work_ptr wrk);

extern void prep_control_params(params_ptr in);
extern void hamiltonian(params_ptr in);
extern void mean_level(params_ptr in);
extern void momentum(params_ptr in);

//  --  prep.c

extern void init_prep(params_ptr in);
extern void write_out(fftw_complex* in, char* str);
extern void writer_out(double* in, char* str);
extern void read_data(params_ptr in);
extern void stokes_wave(double tol, params_ptr in);


